<?php

declare(strict_types=1);

namespace coder;

use think\facade\Db;

class Coder
{
    /**
     * 生成控制器
     * @param string $table 数据库表名
     * @param string $classAliasName 控制器别名（中文）
     * @param array $ignoreFields 忽略的字段
     */
    public static function genController(string $table, string $classAliasName, $force = false, $ignoreFields = ['id', 'create_time', 'update_time', 'delete_time'])
    {
        $modelName = parse_name($table, 1, true); // parse_name() 来自TP6的helper函数库

        $namespace = 'app\\controller\\adminapi';
        $params = '*';
        $className = $modelName;
        $requestParams = '';
        $checks = '';

        $tableFields = Db::query("show full COLUMNS FROM " . parse_name($modelName));
        foreach ($tableFields as $v) {
            $filed = $v['Field'];
            $comment = $v['Comment'];
            $default = $v['Default'];
            $type = $v['Type'];

            if (in_array($filed, $ignoreFields)) continue;
            $requestParams .= "'$filed',";
            $param_type = in_array($type, ['int', 'tinyint', 'bit']) ? 'number' : 'string';
            $params .= " @param $param_type \${$filed} $comment $default\r\n     *";

            if ($v['Null'] != "NO") continue;
            $check = '|';

            if (str_starts_with($type, 'varchar')) {
                $check .= 'max:' . strCutBetween('(', ')', $type);
            } else {
                switch ($type) {
                    case 'int':
                        $check .= 'number';
                        break;
                    case 'tinyint':
                        $check .= 'number';
                        break;
                    case 'datetime':
                        $check .= 'date';
                        break;
                    case 'date':
                        $check .= 'date';
                        break;
                }
            }
            $check = $check == '|' ? '' : $check;
            $checks .= "'$filed|$comment' => 'require$check',\r\n            ";
        }
        $requestParams = substr($requestParams, 0, strlen($requestParams) - 1);

        $builder = new Builder();

        $builder->loadStub('controller')->setVarList(compact(
            'namespace',
            'params',
            'classAliasName',
            'className',
            'requestParams',
            'checks',
        ))->save(app_path() . 'controller' . DIRECTORY_SEPARATOR . 'adminapi' . DIRECTORY_SEPARATOR, $modelName . '.php', $force);
    }

    /**
     * 生成模型
     * @param string $tableName 表名
     * @param string $aliasName 模型中文名
     */
    public static function genModel(string $tableName, string $aliasName, $force = false)
    {
        $fields = Db::query("show full COLUMNS FROM " . $tableName);
        $ds = DIRECTORY_SEPARATOR;
        $br = "\r\n";
        $modelName = parse_name($tableName, 1, true); // parse_name() 来自TP6的helper函数库

        // 默认配置
        $options = [
            'save_dir' => app_path() . "model${ds}",                        // 文件保存目录
            'save_name' => "${modelName}.php",                              // 存为文件名
            'has_pswd' => in_array($modelName, ['Admin']),                  // 是否有密码登陆（使用HasPswdTrait）
            'login' => in_array($modelName, ['Admin', 'User']),             // 是否可登陆（使用LoginCacheTrait）
        ];

        // === 开始处理变量 ===

        // 软删除
        $softDelete = array_search('delete_time', array_column($fields, 'Field')); // 包含delete_time字段的，有软删除
        if ($softDelete !== false) {
            $softDelete = $fields[$softDelete]['Field'];
        }

        $jsonsFields = [];
        foreach ($fields as $field) {
            $fieldType = $field['Type'];
            $fieldField = $field['Field'];

            // 处理json字段
            if ($fieldType == 'json') {
                $jsonsFields[] = "'$fieldField'";
            }
            // 处理关联
            // if(str_ends_with($fieldField, '_id')){

            // }
        }
        $json = 'protected $json = [' . implode(', ', $jsonsFields) . '];';

        $hidden = [];
        if ($softDelete) $hidden[] = $softDelete;
        if ($options['has_pswd']) {
            $hidden[] = 'pswd';
            $hidden[] = 'pswd_salt';
        }
        $hidden = !count($hidden)
            ? ''
            : implode(', ', array_map(fn ($i) => "'$i'", $hidden));


        $vars = [
            'namespace' => 'app\\model',
            'className' => $modelName,
            'tableName' => $tableName,
            'aliasName' => $aliasName,
            'softDelete' => 'use SoftDelete;' . $br . '    protected $deleteTime = \'' . $softDelete . '\';' . $br . '    protected $defaultSoftDelete = 0;',
            'jsonData' => $json,
            'loginContruct' => !$options['login']
                ? ''
                : '// 配置登陆缓存状态' . $br . '        $this->setLoginCacheOption([' . $br . "            'expire_time' => 7200, //2 小时" . $br . '        ]);',
            'updateLoginCache' => !$options['login']
                ? ''
                : '// 更新数据到缓存中' . $br . '        $model->updateLoginCache(true);',
            'updateLoginInfo' => !$options['login']
                ? ''
                : '/**
     * 储存登录信息
     */
    public function updateLoginInfo(): self
    {
        $this->save([
            \'last_login_ip\' => request()->ip(),
            \'last_login_time\' => date(\'Y-m-d H:i:s\'),
        ]);
        return $this;
    }',
            'hidden' => 'protected $hidden = [' . $hidden . '];',
        ];


        $builder = new Builder();
        $builder->loadStub('model')->setVarList($vars)->save($options['save_dir'], $options['save_name'], $force);
    }
}
